﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace FormicArch.AssetBundleEditor
{
    [CreateAssetMenu(menuName = "AssetBundlePath", fileName = "AssetBundlePathData.asset")]
    public class AssetBundlePath : ScriptableObject, ISerializationCallbackReceiver
    {
        public AssetbundleClassify[] AssetbundleLoadPathInfos =
        {
            new AssetbundleClassify
            {
                AssetPath = "Assets/Res/Streaming",
                AssetbundleRealityPath = "resstreaming",
                LoadType = AssetbundleLoadType.Streaming,
            },
            //游戏预加载资源
            new AssetbundleClassify
            {
                AssetPath = "Assets/Res/Preload",
                AssetbundleRealityPath = "preload",
                LoadType = AssetbundleLoadType.Preload,
            },
            //游戏实时加载资源
            new AssetbundleClassify
            {
                AssetPath = "Assets/Res/RealTimeLoading",
                AssetbundleRealityPath = "realtimeloading",
                LoadType = AssetbundleLoadType.NetRealTime,
            },
        };

        [Tooltip("本地依赖资源路径")] public AssetbundleClassify LocalDependenciesPath = new AssetbundleClassify
        {
            AssetbundleRealityPath = "dependenciesstreaming",
            LoadType = AssetbundleLoadType.Streaming,
        };

        [Tooltip("网络资源依赖路径")] public AssetbundleClassify NetworkDependenciesPath = new AssetbundleClassify
        {
            AssetbundleRealityPath = "dependenciespreload",
            LoadType = AssetbundleLoadType.Preload,
        };

        [Tooltip("实时加载资源依赖路径")] public AssetbundleClassify RealTimeDependenciesPath = new AssetbundleClassify
        {
            AssetbundleRealityPath = "dependenciesrealtimeloading",
            LoadType = AssetbundleLoadType.NetRealTime,
        };

        private Dictionary<string, AssetbundleClassify> dict = new();

        private Dictionary<AssetbundleLoadType, AssetbundleClassify> typeDependDict = new();

        private List<AssetbundleClassify> dependList = new();

        private Dictionary<AssetbundleLoadType, List<AssetbundleClassify>> typeDict = new();

        public void OnBeforeSerialize()
        {
        }

        public void OnAfterDeserialize()
        {
            Init();
        }

        public void Init()
        {
            dict.Clear();
            typeDependDict.Clear();
            typeDict.Clear();
            List<AssetbundleClassify> temp;
            foreach (var rootPath in AssetbundleLoadPathInfos)
            {
                //禁止AssetPath重复
                if (!rootPath.Isused)
                {
                    continue;
                }

                dict.Add(rootPath.AssetPath, rootPath);

                if (!typeDict.TryGetValue(rootPath.LoadType, out temp))
                {
                    temp = new List<AssetbundleClassify>();
                    typeDict.Add(rootPath.LoadType, temp);
                }

                temp.Add(rootPath);
            }

            
            Debug.LogWarning($"路径总数{typeDict.Count}");
            setDepend();
        }

        private void setDepend()
        {
            typeDependDict.Add(AssetbundleLoadType.Streaming, LocalDependenciesPath);
            typeDependDict.Add(AssetbundleLoadType.Preload, NetworkDependenciesPath);
            typeDependDict.Add(AssetbundleLoadType.NetRealTime, RealTimeDependenciesPath);
            dependList = typeDependDict.Values.ToList();
        }

        public AssetbundleClassify GetLoadType(string unityPath)
        {
            foreach (var rootPath in AssetbundleLoadPathInfos)
            {
                if (unityPath.StartsWith(rootPath.AssetPath))
                {
                    return rootPath;
                }
            }

            return null;
        }

        /// <summary>
        /// 判断资源路径是否在依赖目录下
        /// </summary>
        /// <param name="realPath">实际打包后资源路径（即资源包名assetbundleName）</param>
        /// <returns></returns>
        public AssetbundleClassify GetDependClassify(string realPath)
        {
            AssetbundleClassify dependPath;
            foreach (var info in dependList)
            {
                if (realPath.StartsWith(info.AssetbundleRealityPath))
                {
                    return info;
                }
            }

            return null;
        }

        public AssetbundleClassify GetDependClassify(AssetbundleLoadType loadType)
        {
            AssetbundleClassify dependPath;
            typeDependDict.TryGetValue(loadType, out dependPath);
            return dependPath;
        }

        public bool IsLoadType(string path, AssetbundleLoadType loadType)
        {
            AssetbundleClassify classify = GetClassifyLoadType(path, loadType);
            return classify != null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="loadType"></param>
        /// <returns></returns>
        public AssetbundleClassify GetClassifyLoadType(string path, AssetbundleLoadType loadType)
        {
            List<AssetbundleClassify> classify;
            if (typeDict.TryGetValue(loadType, out classify))
            {
                return classify.Find(item => path.StartsWith(item.AssetPath));
            }

            return null;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="loadType"></param>
        /// <returns></returns>
        public List<AssetbundleClassify> GetClassifyListLoadType(AssetbundleLoadType loadType)
        {
            if (typeDict.TryGetValue(loadType, out List<AssetbundleClassify> classify))
            {
                return classify;
            }

            return null;
        }

        public List<string> GetGroupNames()
        {
            List<string> groupNames = new List<string>();
            foreach (var classfy in typeDict)
            {
                groupNames.AddRange(classfy.Value.Select(item => item.AssetbundleRealityPath));
            }

            foreach (var classfy in typeDependDict)
            {
                groupNames.Add(classfy.Value.AssetbundleRealityPath);
            }

            return groupNames;
        }
    }
}